package com.syf.kit.soa.core.send.protocol;

import com.syf.kit.soa.core.send.protocol.exception.RpcResponseTimeoutException;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * rpc发送与响应的信息同步器
 * <p>
 * R是响应数据体
 */
public class TcpResponseLatch<R> {
    private long requestNo;

    private CountDownLatch latch;

    public TcpResponseLatch(long requestNo) {
        this.requestNo = requestNo;
        this.latch = new CountDownLatch(1);
    }

    private R response;

    /**
     * attach 响应体
     */
    public void attachResponse(R response) {
        this.response = response;
        latch.countDown();
    }

    /**
     * 阻塞式获取响应体。超时返回null.
     *
     * @param timeoutMs 获取请求提的超时时间，单位：毫秒
     */
    public R getResponse(long timeoutMs) throws RpcResponseTimeoutException {
        try {
            if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) {
                TcpResponseCoordinator.getInstance().deregisterSendLatch(requestNo);
                latch.countDown();
                throw new RpcResponseTimeoutException();
            }

            TcpResponseCoordinator.getInstance().deregisterSendLatch(requestNo);
            return response;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
